package com.meihuayishu.backend.service.impl;

import com.meihuayishu.backend.dto.DivinationFeedbackDTO;
import com.meihuayishu.backend.entity.DivinationFeedback;
import com.meihuayishu.backend.repository.FeedbackRepository;
import com.meihuayishu.backend.service.FeedbackService;
import com.meihuayishu.backend.util.DivinationAccuracyAnalyzer;
import com.meihuayishu.backend.util.EnhancedCityElementData;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 占卜反馈服务实现
 * 增强版支持更精确的反馈分析和权重调整
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class FeedbackServiceImpl implements FeedbackService {
    
    private final FeedbackRepository feedbackRepository;
    private final EnhancedCityElementData cityElementData;
    private final DivinationAccuracyAnalyzer accuracyAnalyzer;
    
    @Override
    public DivinationFeedback saveFeedback(DivinationFeedback feedback) {
        // 设置创建时间
        feedback.setCreatedAt(LocalDateTime.now());
        
        // 保存反馈
        DivinationFeedback savedFeedback = feedbackRepository.save(feedback);
        
        // 如果反馈包含准确性评价，更新城市卦象权重
        if (feedback.getIsAccurate() != null && feedback.getUserCity() != null && feedback.getOriginalHexagram() != null) {
            cityElementData.adjustCityHexagramWeight(
                feedback.getUserCity(),
                feedback.getOriginalHexagram(),
                feedback.getIsAccurate()
            );
            log.debug("已更新城市卦象权重: 城市={}, 卦象={}, 准确={}", 
                feedback.getUserCity(), feedback.getOriginalHexagram(), feedback.getIsAccurate());
        }
        
        return savedFeedback;
    }
    
    @Override
    public List<DivinationFeedbackDTO> getFeedbackByUserId(Long userId) {
        List<DivinationFeedback> feedbacks = feedbackRepository.findByUserIdOrderByCreatedAtDesc(userId);
        
        return feedbacks.stream()
            .map(this::convertToDTO)
            .collect(Collectors.toList());
    }
    
    @Override
    public Map<String, Double> getHexagramAccuracyRates() {
        Map<String, Double> accuracyRates = new HashMap<>();
        
        // 获取所有卦象
        List<String> hexagrams = feedbackRepository.findDistinctOriginalHexagram();
        
        for (String hexagram : hexagrams) {
            // 计算准确率
            long total = feedbackRepository.countByOriginalHexagram(hexagram);
            long accurate = feedbackRepository.countByOriginalHexagramAndIsAccurate(hexagram, true);
            
            if (total > 0) {
                double rate = (double) accurate / total;
                accuracyRates.put(hexagram, rate);
            }
        }
        
        return accuracyRates;
    }
    
    @Override
    public Map<String, Double> getCityAccuracyRates() {
        Map<String, Double> accuracyRates = new HashMap<>();
        
        // 获取所有城市
        List<String> cities = feedbackRepository.findDistinctUserCity();
        
        for (String city : cities) {
            if (city == null) continue;
            
            // 计算准确率
            long total = feedbackRepository.countByUserCity(city);
            long accurate = feedbackRepository.countByUserCityAndIsAccurate(city, true);
            
            if (total > 0) {
                double rate = (double) accurate / total;
                accuracyRates.put(city, rate);
            }
        }
        
        return accuracyRates;
    }
    
    @Override
    public Map<String, Double> getMoodAccuracyRates() {
        Map<String, Double> accuracyRates = new HashMap<>();
        
        // 获取所有心情
        List<String> moods = feedbackRepository.findDistinctUserMood();
        
        for (String mood : moods) {
            if (mood == null) continue;
            
            // 计算准确率
            long total = feedbackRepository.countByUserMood(mood);
            long accurate = feedbackRepository.countByUserMoodAndIsAccurate(mood, true);
            
            if (total > 0) {
                double rate = (double) accurate / total;
                accuracyRates.put(mood, rate);
            }
        }
        
        return accuracyRates;
    }
    
    @Override
    public double getUserAccuracyRate(Long userId) {
        // 使用增强版分析器获取用户准确率
        return accuracyAnalyzer.getUserAccuracyRate(userId);
    }
    
    @Override
    @Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行
    public void analyzeAndUpdateWeights() {
        log.info("开始分析反馈数据并更新权重");
        
        try {
            // 使用增强版分析器分析城市卦象准确率
            Map<String, Map<String, Double>> cityHexagramAccuracy = accuracyAnalyzer.analyzeCityHexagramAccuracy();
            log.info("城市卦象准确率分析完成，共 {} 个城市", cityHexagramAccuracy.size());
            
            // 使用增强版分析器分析心情卦象准确率
            Map<String, Map<String, Double>> moodHexagramAccuracy = accuracyAnalyzer.analyzeMoodHexagramAccuracy();
            log.info("心情卦象准确率分析完成，共 {} 种心情", moodHexagramAccuracy.size());
            
            // 获取卦象准确率（兼容旧版）
            Map<String, Double> hexagramRates = getHexagramAccuracyRates();
            log.info("卦象准确率统计: {}", hexagramRates);
            
            // 获取城市准确率（兼容旧版）
            Map<String, Double> cityRates = getCityAccuracyRates();
            log.info("城市准确率统计: {}", cityRates);
            
            // 获取心情准确率（兼容旧版）
            Map<String, Double> moodRates = getMoodAccuracyRates();
            log.info("心情准确率统计: {}", moodRates);
            
            // 自动调整权重已在分析器中完成
            log.info("反馈数据分析和权重更新完成");
        } catch (Exception e) {
            log.error("反馈数据分析失败", e);
        }
    }
    
    /**
     * 将实体转换为DTO
     * @param feedback 反馈实体
     * @return 反馈DTO
     */
    private DivinationFeedbackDTO convertToDTO(DivinationFeedback feedback) {
        DivinationFeedbackDTO dto = new DivinationFeedbackDTO();
        dto.setId(feedback.getId());
        dto.setUserId(feedback.getUserId());
        dto.setDivinationType(feedback.getDivinationType());
        dto.setOriginalHexagram(feedback.getOriginalHexagram());
        dto.setChangedHexagram(feedback.getChangedHexagram());
        dto.setIsAccurate(feedback.getIsAccurate());
        dto.setFeedbackComment(feedback.getFeedbackComment());
        dto.setUserCity(feedback.getUserCity());
        dto.setUserMood(feedback.getUserMood());
        dto.setCreatedAt(feedback.getCreatedAt());
        return dto;
    }
}